#include "ApplicationsConfig.h"

#include "RegistryHelper.h"
#include "RegexDefs.h"



using namespace platform;


namespace config {

#define REGISTRY_ROOT_KEY							_T("Config\\Collector\\Applications")

#define REGISTRY_VALUE_IS_ENABLED					_T("EnableMonitoring")
#define REGISTRY_MONITORING_ENABLED_VALUE			1
#define REGISTRY_MONITORING_DISABLED_VALUE			0

#define REGISTRY_VALUE_APP_SELECTION_TYPE			_T("AppSelection")
#define REGISTRY_VALUE_APP_SELECTION_ALL			_T("All")
#define REGISTRY_VALUE_APP_SELECTION_ALL_EXCEPT		_T("AllExcept")
#define REGISTRY_VALUE_APP_SELECTION_SELECTED_ONLY	_T("ListOnly")

#define REGISTRY_VALUE_APP_LIST						_T("Applications")
#define APP_LIST_SEPARATOR_CHAR						_T(';')

ApplicationsConfig::ApplicationsConfig(void) {
	// TODO: HANDLE DEFAULT VALUES IF NOT FOUND
	try {
		RegistryHelper::RegistryKey key(RegistryHelper::RK_ABPA_BASE, REGISTRY_ROOT_KEY);

		m_isMonitoringEnabled = (key.getInt32Value(REGISTRY_VALUE_IS_ENABLED) == REGISTRY_MONITORING_ENABLED_VALUE);

		XString strAppSelection;
		key.getStringValue(REGISTRY_VALUE_APP_SELECTION_TYPE, strAppSelection);
		if (strAppSelection == REGISTRY_VALUE_APP_SELECTION_ALL)
			m_stype = AST_ALL;
		else if (strAppSelection == REGISTRY_VALUE_APP_SELECTION_ALL_EXCEPT)
			m_stype = AST_EXCEPT_FOR_SELECTED;
		else if (strAppSelection == REGISTRY_VALUE_APP_SELECTION_SELECTED_ONLY)
			m_stype = AST_ONLY_SELECTED;
		else {
			m_isMonitoringEnabled = false;
			return;
		}

		XString strAppList;
		key.getStringValue(REGISTRY_VALUE_APP_LIST, strAppList);
		strAppList.split(APP_LIST_SEPARATOR_CHAR, m_listApp);

	} catch (Exception &) {
		m_isMonitoringEnabled = false;
	}
}



void ApplicationsConfig::do_save(void) const 
{
	RegistryHelper::RegistryKey key(RegistryHelper::RK_ABPA_BASE, REGISTRY_ROOT_KEY);

	key.setValue(REGISTRY_VALUE_IS_ENABLED, 
		(m_isMonitoringEnabled ? REGISTRY_MONITORING_ENABLED_VALUE : REGISTRY_MONITORING_DISABLED_VALUE));

	XString strAppSelection;
	switch (m_stype) {
	case AST_ALL:
		strAppSelection = REGISTRY_VALUE_APP_SELECTION_ALL;
		break;
	case AST_EXCEPT_FOR_SELECTED:
		strAppSelection = REGISTRY_VALUE_APP_SELECTION_ALL_EXCEPT;
		break;
	case AST_ONLY_SELECTED:
		strAppSelection = REGISTRY_VALUE_APP_SELECTION_SELECTED_ONLY;
		break;
	}
	key.setValue(REGISTRY_VALUE_APP_SELECTION_TYPE, strAppSelection);

	XString strAppList;
	m_listApp.join(APP_LIST_SEPARATOR_CHAR, strAppList);
	key.setValue(REGISTRY_VALUE_APP_LIST, strAppList);
}

inline bool ApplicationsConfig::appMatchesOneOfDefined(const platform::XString &name) const
{
	for (platform::XStringList::const_iterator it = m_listApp.begin(); it != m_listApp.end(); ++it) {
		tregex nextFile(it->getTStr(), boost::regex::perl | boost::regex::icase);
		if (boost::regex_match(name.getTStr(), nextFile))
			return true;
	}
	return false;
}

bool ApplicationsConfig::shouldAttachToApplication(const XString &name) const 
{
	if (!m_isMonitoringEnabled)
		return false;
	return isApplicationEnabled(name);
}

bool ApplicationsConfig::isApplicationEnabled(const XString &name) const 
{
	switch (m_stype) {
	case AST_ALL:
		return true;
	case AST_EXCEPT_FOR_SELECTED:
		return !appMatchesOneOfDefined(name);
	case AST_ONLY_SELECTED:
		return appMatchesOneOfDefined(name);
	default:
		return false;
	}
}

} // end namespace